#pragma once
#include <iostream>
#include <functional>
#include <sys/types.h>
#include <unistd.h>
#include <memory>
#include "Log.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"
#include "Socket.hpp"
using namespace my_log;
using namespace SocketMoudule;
using ioservice_t = function<void(shared_ptr<Socket> &socket, InetAddr &addr)>;
class TcpServer
{
public:
    TcpServer(uint16_t port, ioservice_t service)
        :_service(service),_listensockptr(make_unique<TcpSocket>())
    {
        _listensockptr->BuildTcpServerMoudule(port);
        Start();
    }
    void Start()
    {
        while(true)
        {
            InetAddr addr;
            auto sock = _listensockptr->Accept(&addr);
            if(sock == nullptr) continue;
            LOG(Level::INFO)<<addr.stringaddr()<<"accept success...";
            pid_t pid = fork();
            if(pid < 0)
            {
                LOG(Level::FATAL)<<"fork fail";
                exit(FORK_ERRO);
            }
            if(pid == 0)
            {
                if(fork()>0)
                    exit(SUCCESS);
                _service(sock,addr);
                sock->Close();
                exit(SUCCESS);
            }
            else
            {
                sock->Close();
            }
        }
    }

private:
    ioservice_t _service;
    unique_ptr<Socket> _listensockptr;
};